home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 014 / libtools.arc / SDIR24C.AQM / SDIR24C.ASM
Encoding:
Assembly Source File  |  1984-04-08  |  31.4 KB  |  932 lines

  1.     TITLE   SDIR - SORTED DIRECTORY COMMAND, Version 2.4
  2.     PAGE    64,132                  ; JAN 1983
  3. COMMENT |
  4.     SDIR [d:][path][filename[.ext]] [options]                2.4
  5.      [filespec] same as for DIR command
  6.  
  7.      [options] * /A - List hidden files.
  8.            * /E - Without screen erase.
  9.            * /P - Pause when screen full.
  10.          /X - Sort by extension.
  11.          /S - Sort by size.
  12.          /D - Sort by date/time.
  13.          /N - Do not sort, original order.
  14.  
  15.        Default = *.* sorted by name.ext with screen erase.
  16.        * - Option may be combined with other options.
  17.  
  18.    This source file was created from an object file obtained
  19.  from Gene Plantz's BBS in Chicago. The original file name
  20.  was SD.HEX.  I then used DEBUG and CAPTURE to get the first
  21.  dis-assembly which  was then edited with WORDSTAR to create
  22.  a source that when assembled using MASM would duplicate the
  23.  original object file.
  24.    Comments have been added and I do hope they are helpful.
  25.  I have made several modifications to the first version and
  26.  am continuing to add comments.  This source file is an
  27.  excellent example for anyone wishing to learn 8086/8088
  28.  assembly language.  Use at your own risk and feel free to
  29.  share this file with your friends.
  30.    I certainly wish that John Chapman would publish his
  31.  source file.  His comments are sure to be more meaningful
  32.  than mine could ever be.  Some of the conversion routines
  33.  are very elegant, but difficult to understand.  As far as
  34.  I'm concerned, PRINTDD is magic.
  35.    Several modifications have been made.  They are:
  36.  
  37.     1. Filespecs are processed like DIR does.
  38.     2. No sort option was added. /N
  39.     3. Pause when screen full option added. /P
  40.     4. Number of files found is printed.
  41.  
  42.                     Ted Reuss
  43.                     Houston, TX
  44.  
  45.     SDIR Version 2.2  The GETFREE Subroutine was updated for DOS 2.0
  46.     April 1, 1983   by     Jack Y. Fong
  47.     Changes are denoted by "JYF" at the end of changed lines.
  48.  
  49.  
  50.     SDIR Version 2.3:
  51.     Added display of current directory name and volume name
  52.         in header lines for DOS Release 2.0.
  53.     Added total of file sizes for the displayed files.
  54.         This is helpful in DOS 2.0 since it allows you to determine
  55.         the number of bytes used by all the files in a root or
  56.         subdirectory (or used by a specified subset of
  57.         the files in a root or subdirectory).
  58.  
  59.     John F. Ratti    29 June, 1983
  60.     Changes are denoted by "2.3" at the end of the changed lines.
  61.  
  62.     SDIR Version 2.4:
  63.     Added display of attribute byte. The column 'ATR' will display
  64.         up to 4 attribute codes. The codes are as follows:
  65.         A - Archive bit is off (file has been archived)
  66.         H - Hidden bit is on (file is hidden)
  67.         R - Read-only bit is on (file is read-only)
  68.         S - System bit is on (file is a system file)
  69.     Corrected display of hidden, system, read-only and directory
  70.         entries when /a option is specified.
  71.     Added pathname capability. Any pathname that DIR will accept
  72.         will work. The code should have been rewritten, rather than
  73.         modified. The resulting code is somewhat obtuse, and I
  74.         apologize for it. I plan to write a proper pathname
  75.         parser. When I do, I'll incorporate it into SDIR.
  76.     This version MUST be used under MS-DOS release 2.0.
  77.     John F. Ratti    03 July, 1983
  78.     Changes are denoted by "2.4" at the end of the changed lines.
  79. |
  80.  
  81.     SUBTTL  EQUATES & STRUCTURES
  82.     PAGE
  83. IF1
  84. DOSCALL MACRO        FUNC,PARM1
  85. .xcref
  86. F_C =        FUNC
  87. IFNB <PARM1>
  88. IF F_C EQ 2 OR (F_C GE 4 AND F_C LE 6) OR F_C EQ 14 OR F_C EQ 46
  89.     MOV     DL,PARM1
  90. ELSE
  91.     MOV     DX,OFFSET PARM1
  92. ENDIF
  93. ENDIF
  94.     MOV    AH,FUNC
  95.     INT    21H
  96. .cref
  97.     ENDM
  98. ENDIF
  99. .SALL    ;supress all macro expansions
  100. ;    PC-DOS INTERRUPT 21H FUNCTION CODES
  101. ;
  102. @CHROUT EQU    2    ;display char in DL
  103. @KEYIN    EQU    8    ;kybd input w/o echo
  104. @STROUT EQU    9    ;print string terminated with $
  105. @CKEYIN EQU    12    ;clr kybd bufr & do inp.func in AL
  106. @OPEN    EQU    15    ;open XFCB                    2.4
  107. @SRCH1    EQU    17    ;search for first dir entry
  108. @SRCH2    EQU    18    ;search for next dir entry
  109. @GETDSK EQU    25    ;get default disk drive
  110. @SETDTA EQU    26    ;set disk transfer addr
  111. @FATAD2 EQU    28    ;get FAT of drive # in DL
  112. @PARSEF EQU    41    ;parse filename
  113. @GETDTE EQU    42    ;get system date
  114. @GETTME EQU    44    ;get system time
  115. @GETVER EQU    30H    ;get version number                JYF
  116. @CTLBRK EQU    33H    ;get/set ctrl/break checking            2.4
  117. @DSKFSP EQU    36H    ;get disk free space                JYF
  118. @CHDIR    EQU    3BH    ;change directory                2.4
  119. @CHMOD    EQU    43H    ;change/get file mode                2.4
  120. @GETCD    EQU    47H    ;get current directory                2.3
  121. @FIND1    EQU    4EH    ;find first dir. entry (DOS 2.0)        2.4
  122. @FIND2    EQU    4FH    ;find next dir entry (DOS 2.0)            2.4
  123.  
  124. CR  EQU     0DH     ;carriage return
  125. LF  EQU     0AH     ;line feed
  126. FCB_1        EQU     5CH     ;fcb for parameter 1
  127. PARAM_L EQU 80H     ;# characters in PARAM_B
  128. PARAM_B EQU 81H     ;DOS cmd parameter buffer.
  129.  
  130. ; PC-DOS packed date   <yyyyyyym mmmddddd>
  131. P_DTE        RECORD  P_YR:7,P_MO:4,P_DY:5
  132. ; PC-DOS packed time   <hhhhhmmm mmmsssss>
  133. P_TME        RECORD  P_HR:5,P_MI:6,P_2S:5
  134.  
  135. DIR     RECORD  P_YR:7,P_MO:4,P_DY:5
  136. ; PC-DOS packed time   <hhhhhmmm mmmsssss>
  137. P_TME        RECORD  P_HR:5,P_MI:6,P_2S:5
  138.  
  139. DIRNTRY STRUC            ;directory entry structure
  140. LNK DW        0        ;ptr to next entry
  141. NAM DB        8 DUP(0),'.' ;filename
  142. EXT DB        3 DUP(0) ;extension
  143. TME DW        0        ;time
  144. DTE    DW    0    ;date
  145. SZL    DW    0    ;low word of size
  146. SZH    DW    0    ;high word of size
  147. ATR    DB    0    ;attribute byte                 2.4
  148. DIRNTRY ENDS
  149.  
  150.     SUBTTL    DATA AREA & INITIALIZATION
  151.     PAGE
  152. SDIR    SEGMENT PUBLIC 'CODE'
  153.     ASSUME    CS:SDIR,DS:SDIR,ES:SDIR
  154.     ORG    100H
  155. MAIN    PROC    FAR
  156.     JMP    STARTS
  157.  
  158. DIRLNK    DW    DIRBUF    ;ptr to next opening in DIRBUF
  159. C1LNK    DW    0    ;ptr to row 1, column 1
  160. C2LNK    DW    0    ;ptr to row 1, column 2
  161. NBRFILS DW    0    ;# of files or detail lines
  162. SRTFLG    DB    0    ;if = 0 then sort else no sort
  163. CLSFLG        DB        0        ;if = 0 then clear screen
  164. EXTFLG        DB        0        ;if <> 0 then sort by ext
  165. SIZFLG        DB        0        ;if <> 0 then sort by size
  166. DTEFLG        DB        0        ;if <> 0 then sort by date/time
  167. PSEFLG        DB        0        ;if <> 0 then pause if screen full
  168. LPERSCR EQU 25        ;Lines per screen
  169. LINCNT        DB        LPERSCR-5 ;Number of lines left
  170. PSEMSG        DB        'Strike a key when ready . . . $'
  171.  
  172. HDNG1        DB        'SDIR: Sorted DIRectory listing, Version 2.4  ';   2.3
  173.         DB        'Volume '            ;                             2.3
  174. VOLNAME     DB        '             ' ;                                  2.3
  175. D_MM        DW        '00'            ;Month
  176.     DB        '/'
  177. D_DD        DW        '00'            ;Day
  178.     DB        '/'
  179. D_YY        DW        '00'            ;Year
  180.     DB        ' '
  181. T_HH        DW        '00'            ;Hours
  182.     DB        ':'
  183. T_MM        DW        '00'            ;Minutes
  184.         DB        CR,LF,'$'       ;                                  2.3
  185. HDNG2        DB        32 DUP(' ')     ;                                  2.3
  186.         DB        'Directory of ' ;                                  2.3
  187. HDRVE        DB        '@:'            ;                                  2.3
  188. DIRNAME     DB        '\',69 DUP(0)       ; directory name                2.4
  189.         DB        LF,LF,CR,'$'    ;                                  2.3
  190. CRLF    DB    CR,LF,'$'
  191. LFLFCR    DB    LF,LF,CR,'$'            ;literal for a blank line       2.3
  192. HDNG3    DB    'FILESPEC.EXT  BYTES ATR -LAST  CHANGE-$'
  193.     DB    8 DUP(' ')
  194. SPACES    DB    '$'
  195. HDNG4    DB    ' Bytes in $'                   ;                       2.3
  196. HDNG5    DB    ' File(s); ','$'                ;                       2.4
  197. HDNG6    DB    ' bytes free.',CR,LF,'$'        ;                       2.4
  198.  
  199.     SUBTTL    DISK TRANSFER AREA & FREE SPACE ENTRY DEFS
  200.     PAGE
  201.  
  202.     DB    'PATH NAME='
  203. PATHD    DB    '@:'
  204. PATH    DB    64 DUP(0)    ;hold area for pathname         2.4
  205.  
  206. XFCB    DB    -1,7 DUP(0),11 DUP('?'),25 DUP(0)
  207. ATTRIB    EQU    XFCB+6        ;file attribute
  208. DRVNUM    EQU    ATTRIB+1    ;drive # (1=A, 2=B, etc.)
  209.  
  210. DTA    DB    40 DUP(0)    ;Disk Transfer Area used
  211. XNAME    EQU    DTA+8        ;volume name                2.4
  212. FILNAME EQU    DTA+30        ;by FIND for the            2.4
  213. FILTIME EQU    DTA+22        ;directory search.            2.4
  214. FILSIZE EQU    DTA+26        ;                    2.4
  215. FILATTR EQU    DTA+21        ;(file attribute byte)            2.4
  216.  
  217. FREESPC DW    0        ;Free space entry.
  218.     DB    '*FREE SPACE*',4 DUP(0)
  219. LOSIZE    DW    0        ;of free space
  220. HISIZE    DW    0        ;of free space
  221.  
  222. LOTOTAL DW    0        ;total size of all files: low word    2.3
  223. HITOTAL DW    0        ;total size of all files: high word    2.3
  224.  
  225. PATHLEN DW    0        ;length of subdirectories in pathname    2.4
  226. HOLDATR DB    0        ;hold area for XFCB attribute byte    2.3
  227. HOLDLEN DW    0        ;hold area for length of directory name 2.3
  228.  
  229. DBLCNT    DW    0        ;current offset into DOUBLE        2.4
  230. DOUBLE    DB    8 DUP(' '),'$'  ;destination for PRINTDX                2.4
  231.  
  232. PRTATR    DB    5 DUP(' '),'$'  ;area to build ATR for printing         2.4
  233. INITATR DB    5 DUP(' ')      ;used to re-init ATR                    2.4
  234.  
  235. PRTDIR    DB    '  <DIR>$'      ;literal used to denote directories     2.4
  236. ALLF    DB    '*.*'           ;literal for displaying all files       2.4
  237. PATHALL DB    '\*.*',0        ;same as above for subdirectories       2.4
  238.  
  239. DRVNBR    DB    0        ;place to hold working drive number    2.4
  240.  
  241. CURDSK    DB    '@:\'           ;hold area for current dirname so we can2.4
  242. CURDIR    DB    64 DUP(0)    ;restore it later            2.4
  243.  
  244. PATHNF    DB    'Path not found$' ;error message literal                2.4
  245.  
  246.     SUBTTL    MAIN PROGRAM SECTION
  247.     PAGE
  248. STARTS:
  249.     PUSH    DS        ;Set up the
  250.     XOR    AX,AX        ; stack for a
  251.     PUSH    AX        ; return to DOS.
  252.     CALL    GETARGS     ;Process arguments
  253.     CALL    SRCHDIR     ;Search directory
  254.     CMP    SRTFLG,0    ;Check if any sort
  255.     JZ    A1        ; option selected.
  256.     CALL    LNKDIRB     ;Leave in original
  257.     JMP    SHORT A2    ; directory order.
  258. A1:    CALL    SRTDIRB     ;Sort by major key
  259. A2:    CALL    GETFREE     ;Get free space
  260.     CALL    SPLTLST     ;Set up for 2 columns
  261.     CALL    PRTHDNG     ;Print headings
  262.     CALL    PRTDRVR     ;Print detail lines
  263.     CALL    PRTNFLS     ;Print byte total and # of files    2.3
  264.     RET            ;Return to DOS
  265. MAIN    ENDP
  266.  
  267.     SUBTTL    GETARGS - PROCESS ARGUMENTS
  268.     PAGE
  269. GETARGS PROC    NEAR
  270.     MOV    DI,PARAM_L    ;point to command buffer length     2.4
  271.     XOR    CH,CH        ;clear high-order byte            2.4
  272.     MOV    CL,BYTE PTR [DI] ;get length                2.4
  273.     JCXZ    G24F        ;jump if no param provided        2.4
  274.     INC    DI        ;point to command buffer        2.4
  275.     MOV    AL,' '          ;we'll search for the first non-blank   2.4
  276.     CLD            ;search forward             2.4
  277.     REPE    SCASB        ;find first non-blank            2.4
  278.     JE    G24F        ;all blanks: treat like no parm provided2.4
  279.     INC    CX        ;and adjust length            2.4
  280.     DEC    DI        ;adjust offset                2.4
  281.     MOV    SI,DI        ;save offset of first non-blank     2.4
  282.     MOV    DX,CX        ;save cx                2.4
  283.     MOV    AL,'/'          ;search for a slash                     2.4
  284.     CLD            ;clear direction flag            2.4
  285.     REPNE    SCASB        ;search for a slash            2.4
  286.     JCXZ    G24A        ;jump if slash not found        2.4
  287.     INC    CX        ;adjust cx if slash found        2.4
  288. G24A:    NEG    CX        ;subtract count from original length    2.4
  289.     ADD    CX,DX        ;to get length of drive+path        2.4
  290.     JCXZ    G24F        ;if 0, only options specified        2.4
  291.     MOV    DI,OFFSET PATH    ;point to path name hold area        2.4
  292.     CMP    BYTE PTR [SI+1],':' ;was drive number specified?        2.4
  293.     JNE    G24B        ;No, go move the path            2.4
  294.     INC    SI        ;point past drive number        2.4
  295.     INC    SI        ;point past :                2.4
  296.     DEC    CX        ;adjust...                2.4
  297.     DEC    CX        ;...length                2.4
  298.     JNZ    G24B        ;if any characters remain process them    2.4
  299. G24F:    MOV    SI,OFFSET ALLF    ;point to the all-files literal     2.4
  300.     MOV    DI,OFFSET PATH    ;the path needs it            2.4
  301.     MOV    CX,3        ;length of literal            2.4
  302.     CLD            ;to assure forward direction        2.4
  303.     REP    MOVSB        ;move the literal            2.4
  304.     JMP    G24C        ;now process normally            2.4
  305. G24B:    CLD            ;clear direction flag            2.4
  306.     MOV    DX,CX        ;save the length            2.4
  307.     REP    MOVSB        ;and move the pathname to path        2.4
  308.     CMP    DX,1        ;is length of pathname 1?        2.4
  309.     JNE    G24C        ;no                    2.4
  310.     CMP    PATH,'\'        ;is the only character a backslash?     2.4
  311.     JNE    G24C        ;no                    2.4
  312.     MOV    SI,OFFSET ALLF    ;point to the all-files literal     2.4
  313.     MOV    DI,OFFSET PATH+1 ;the path needs it            2.4
  314.     MOV    CX,3        ;length of literal            2.4
  315.     CLD            ;to assure forward direction        2.4
  316.     REP    MOVSB        ;move the literal            2.4
  317. G24C:    MOV    SI,PARAM_B    ;point to cmd buffer            2.4
  318.     MOV    DI,OFFSET DRVNUM ;point to FCB                2.4
  319.     MOV    AL, 1111B    ;Select parse options
  320.     DOSCALL @PARSEF     ;Parse filename
  321.     CMP    BYTE PTR [DI],0 ;If <> 0 then
  322.     JNZ    B1        ; not default drive
  323.     DOSCALL @GETDSK     ;AL <- default disk
  324.     INC    AL        ;Increment drive #
  325.     STOSB            ;Save drive #
  326. B1:    MOV    AL,DRVNUM    ;get drive number            2.4
  327.     MOV    DRVNBR,AL    ;save as working drive number        2.4
  328.     ADD    PATHD,AL    ;convert drive number to ascii        2.4
  329.     XOR    CX,CX        ;clear cx just in case...        2.4
  330.     MOV    AX,0        ;load "get attribute" subfunction code  2.4
  331.     DOSCALL @CHMOD,PATHD    ;get attribute of the current path in cx2.4
  332.     OR    AL,AL        ;check for error            2.4
  333.     JNZ    G24X        ;if so, it's not a directory            2.4
  334.     TEST    CX,10H        ;is it a directory?            2.4
  335.     JZ    G24X        ;no                    2.4
  336.     MOV    DI,OFFSET PATH    ;we need to find the end of PATH    2.4
  337.     MOV    CX,64        ;which can be up to 64 bytes long...    2.4
  338.     MOV    AL,0        ;...so we'll search for a 0             2.4
  339.     CLD            ;search forward             2.4
  340.     REPNE    SCASB        ;find the end of PATH            2.4
  341.     DEC    DI        ;point di at the zero            2.4
  342.     MOV    SI,OFFSET PATHALL ;point to literal            2.4
  343.     MOV    CX,5        ;literal is 5 bytes long        2.4
  344.     CLD            ;i'm a coward                           2.4
  345.     REP    MOVSB        ;now move the literal to the path    2.4
  346. G24X:    MOV    CX,64        ;up to 64 characters in a pathname    2.4
  347.     MOV    AL,'\'          ;we'll search for the last backslash    2.4
  348.     MOV    DI,OFFSET PATH+63 ;point to the end of the pathname    2.4
  349.     STD            ;search backwards            2.4
  350.     REPNE    SCASB        ;for the last backslash         2.4
  351.     MOV    PATHLEN,CX    ;and save path length            2.4
  352.     CMP    PATH,'\'        ;is first path character a backslash?   2.4
  353.     JNE    G24D        ;no, full path not specified        2.4
  354.     MOV    CX,PATHLEN    ;get the length of the subdirectories    2.4
  355.     MOV    SI,OFFSET PATH    ;point to path                2.4
  356.     MOV    DI,OFFSET DIRNAME ;and to dest                2.4
  357.     CLD            ;just in case                2.4
  358.     REP    MOVSB        ;move the pathname            2.4
  359.     JMP    G24E        ;bypass the rest of this        2.4
  360. G24D:    MOV    SI,OFFSET DIRNAME+1 ;point to directory name field    2.4
  361.     MOV    DL,BYTE PTR DRVNBR ;pick up drive number        2.4
  362.     DOSCALL @GETCD        ;get the current directory        2.4
  363.     MOV    CX,PATHLEN    ;if pathlen is zero, no subdirectories    2.4
  364.     JCXZ    G24E        ;so don't concatenate path              2.4
  365.     MOV    CX,64        ;we're going to find the end of...      2.4
  366.     MOV    AL,0        ;...DIRNAME so we can concatenate...    2.4
  367.     MOV    DI,OFFSET DIRNAME ;...the path subdirectories to it    2.4
  368.     CLD            ;search forwards            2.4
  369.     REPNE    SCASB        ;search for a 0             2.4
  370.     DEC    DI        ;point back to the zero         2.4
  371.     DEC    DI        ;point to last character of current dir 2.4
  372.     CMP    BYTE PTR [DI],'\' ;is the last character a backslash?   2.4
  373.     JNE    G24Z        ;no, it's not a root directory          2.4
  374.     INC    DI        ;adjust pointer             2.4
  375.     JMP    G24Y        ;and skip extra-separator stuff     2.4
  376. G24Z:    INC    DI        ;adjust pointer             2.4
  377.     MOV    AL,'\'          ;get a literal                          2.4
  378.     STOSB            ;to separate the 2 concatenated parts    2.4
  379. G24Y:    MOV    CX,PATHLEN    ;get length of subdirectories        2.4
  380.     MOV    SI,OFFSET PATH    ;move from path to dirname        2.4
  381.     CLD            ;forward move                2.4
  382.     REP    MOVSB        ;now concatenate the dir + pathnames    2.4
  383. G24E:    MOV    AL,0        ;read ctrl/break state into dl        2.4
  384.     DOSCALL @CTLBRK     ;read status                2.4
  385.     PUSH    DX        ;save status                2.4
  386.     MOV    AL,1        ;prepare to set ctl/break state...    2.4
  387.     MOV    DL,0        ;...to OFF...                2.4
  388.     DOSCALL @CTLBRK     ;...so we won't mess up the current dir 2.4
  389.     MOV    DL,BYTE PTR DRVNBR ;get drive number            2.4
  390.     ADD    CURDSK,DL    ;convert to ascii            2.4
  391.     ADD    HDRVE,DL    ;convert to ascii            2.4
  392.     MOV    SI,OFFSET CURDIR ;point to current directory save area    2.4
  393.     DOSCALL @GETCD        ;get and save current directory     2.4
  394.     DOSCALL @CHDIR,HDRVE    ;temporarily set current directory    2.4
  395.     CMP    AL,3        ;check for error return         2.4
  396.     JNE    G24Q        ;jump if no error            2.4
  397.     DOSCALL @STROUT,PATHNF    ;issue 'path not found message'         2.4
  398.     INT    20H        ;and get lost                2.4
  399. G24Q:    MOV    DL,BYTE PTR DRVNBR ;get drive number            2.4
  400.     MOV    SI,OFFSET DIRNAME+1 ;point to dirname            2.4
  401.     DOSCALL @GETCD        ;now get the dirname without '\..'s     2.4
  402.     DOSCALL @CHDIR,CURDSK    ;now reset the current directory    2.4
  403.     MOV    AL,1        ;set ctrl/break state...        2.4
  404.     POP    DX        ;...to previous value            2.4
  405.     DOSCALL @CTLBRK     ;and do it                2.4
  406.     MOV    DI,OFFSET DIRNAME ;point to directory name field again    2.4
  407.     MOV    CX,64        ;name can be up to 64 bytes long    2.4
  408.     MOV    AL,0        ;name is terminated by a zero        2.4
  409.     CLD            ;just in case                2.4
  410.     REPNE    SCASB        ;search for the end            2.4
  411.     MOV    AX,64        ;get constant                2.4
  412.     SUB    AX,CX        ;subtract remaining count        2.4
  413.     SHR    AX,1        ;divide result by 2            2.4
  414.     MOV    HOLDLEN,AX    ;and save result            2.4
  415.     DEC    DI        ;adjust pointer             2.4
  416.     MOV    CX,4        ;load length of literal         2.4
  417.     MOV    SI,OFFSET LFLFCR ;point to literal            2.4
  418.     CLD            ;just in case                2.4
  419.     REP    MOVSB        ;and terminate the dirname with literal 2.4
  420.     MOV    SI,PARAM_L    ;SI <- ptr cmd length
  421.     MOV    CH,0
  422.     MOV    CL,[SI]     ;CL <- # chars in cmd
  423.     JCXZ    B10
  424. B2:    INC    SI        ;Point to next char
  425.     CMP    BYTE PTR [SI],'/'
  426.     JNZ    B8        ;If not a slash
  427.     MOV    AL,[SI+1]    ;AL <- option letter
  428.     AND    AL,0DFH     ;Force to upper-case
  429.     CMP    AL,'A'          ;Hidden & system & directory files?
  430.     JNZ    B3        ;Nope, try next one.
  431.     MOV    HOLDATR,2+4+16 ;Hidden & system & directory
  432. B3:    CMP    AL,'E'          ;Without screen erase?
  433.     JNZ    B4        ;Nope, try next one.
  434.     MOV    CLSFLG,AL
  435. B4:    CMP    AL,'S'          ;Sort by size?
  436.     JNZ    B5        ;Nope, try next one.
  437.     MOV    SIZFLG,AL
  438. B5:    CMP    AL,'D'          ;Sort by date/time?
  439.     JNZ    B6        ;Nope, try next one.
  440.     MOV    DTEFLG,AL
  441. B6:    CMP    AL,'X'          ;Sort by extension?
  442.     JNZ    B7        ;Nope, try next one.
  443.     MOV    EXTFLG,AL
  444. B7:    CMP    AL,'N'          ;Original order?
  445.     JNZ    B8        ;Nope, try next one.
  446.     MOV    SRTFLG,AL
  447. B8:    CMP    AL,'P'          ;Pause when screen full?
  448.     JNZ    B9        ;Nope, try next one.
  449.     MOV    PSEFLG,AL
  450. B9:    LOOP    B2        ;Test for another param.
  451. B10:    RET
  452. GETARGS ENDP
  453.  
  454.     SUBTTL    SRCHDIR - SEARCH DIRECTORY
  455.     PAGE
  456. SRCHDIR PROC    NEAR
  457.  
  458.     DOSCALL @SETDTA,DTA    ;Set DTA for dir. search        2.3
  459.     MOV    CX,11        ;we'll move 11...                       2.4
  460.     MOV    AL,'?'          ;...question marks...                   2.4
  461.     MOV    DI,OFFSET XFCB+8 ;...to the XFCB...            2.4
  462.     CLD            ;...in case the filename is crashed...    2.4
  463.     REP    STOSB        ;...so that we can search for the volid 2.4
  464.     MOV    BYTE PTR ATTRIB,8 ;set attribute byte and...        2.3
  465.     DOSCALL @SRCH1,XFCB    ;get the volume name            2.3
  466.     MOV    SI,OFFSET XNAME ;point to filename within xfcb        2.4
  467.     MOV    CX,11        ;load length of volume name        2.3
  468.     MOV    DI,OFFSET VOLNAME ;point to destination field in HDNG1    2.3
  469.     CLD            ;forward, march             2.3
  470.     REP    MOVSB        ;move the volume name            2.3
  471.     MOV    DI,OFFSET DIRNAME ;point to the directory name again    2.3
  472.     MOV    CL,HOLDATR    ;get the real attribute byte        2.4
  473.     XOR    CH,CH        ;clear the high-order byte        2.4
  474.     DOSCALL @FIND1,PATHD    ;First call to search dir.        2.4
  475. C1:    OR    AL,AL
  476.     JNZ    C2        ;Not found, quit looking.
  477.     MOV    BX,DIRLNK    ;BX <- base of DIRBUF
  478.     LEA    DI,[BX].NAM    ;point to beginning of dirntry        2.4
  479.     MOV    SI,OFFSET FILNAME
  480.     MOV    CX,12        ;length of filename            2.4
  481.     CMP    BYTE PTR [SI],'.' ;is first character a period?         2.4
  482.     JNE    C24A        ;no, it's not a special case            2.4
  483.     MOVSB            ;move it to the buffer            2.4
  484.     DEC    CX        ;adjust count                2.4
  485.     CMP    BYTE PTR [SI],'.' ;is next character a period?          2.4
  486.     JNE    C24A        ;no, let normal routine pad the rest    2.4
  487.     MOVSB            ;move it to the buffer            2.4
  488.     DEC    CX        ;adjust count                2.4
  489. C24A:    CMP    BYTE PTR [SI],0 ;is it a zero?                2.4
  490.     JNE    C24B        ;no                    2.4
  491.     MOV    AL,' '          ;load a space into al                   2.4
  492.     REP    STOSB        ;and blank out the rest of the name    2.4
  493.     JMP    C24X        ;and go get other fields        2.4
  494. C24B:    CMP    BYTE PTR [SI],'.' ;is it a period?                      2.4
  495.     JNE    C24C        ;no, process it             2.4
  496.     MOV    DX,CX        ;save CX                2.4
  497.     SUB    CX,4        ;determine number of spaces needed    2.4
  498.     SUB    DX,CX        ;adjust saved CX            2.4
  499.     MOV    AL,' '          ;get a space                            2.4
  500.     REP    STOSB        ;and pad out the name            2.4
  501.     MOV    CX,DX        ;restore CX                2.4
  502. C24C:    MOVSB            ;move the character to the buffer    2.4
  503.     DEC    CX        ;adjust count                2.4
  504.     JNZ    C24A        ;and loop if anything's left to process 2.4
  505. C24X:    MOV    SI,OFFSET FILTIME ;exit point for filename routine    2.4
  506.     MOVSW            ;Move time to DIRBUF
  507.     MOVSW            ;Move date to DIRBUF
  508.     MOV    SI,OFFSET FILSIZE
  509.     MOVSW            ;Move size to DIRBUF
  510.     MOVSW
  511.     MOV    SI,OFFSET FILATTR ;point to file attribute byte     2.4
  512.     MOVSB            ;and move it to dirntry         2.4
  513.     ADD    BX,SIZE DIRNTRY ;Point to next entry
  514.     MOV    DIRLNK,BX    ;Save ptr
  515.     INC    NBRFILS     ;Increment file count
  516.     MOV    CL,HOLDATR    ;get the real attribute byte        2.4
  517.     XOR    CH,CH        ;clear the high-order byte        2.4
  518.     DOSCALL @FIND2,PATHD    ;Search for next file            2.4
  519.     JMP    C1        ;Loop for next one
  520. C2:    RET
  521. SRCHDIR ENDP
  522.  
  523.     SUBTTL    SRTDIRB - SORTS ENTRIES IN DIRBUF
  524.     PAGE
  525. SRTDIRB PROC    NEAR    ;Sorts directory entries in DIRBUF
  526.     MOV    DI,OFFSET DIRBUF ;Point to DIRBUF
  527. D1:    CMP    DI,DIRLNK    ;Are there anymore?
  528.     JNC    D8        ;NO, exit
  529.     MOV    SI,OFFSET C1LNK ;Start with column 1 ptr
  530. D2:    MOV    BX,SI
  531.     MOV    SI,[BX]     ;SI<-ptr to next entry
  532.     OR    SI,SI
  533.     JZ    D7        ;if link=0
  534.     MOV    AX,SI
  535.     MOV    DX,DI
  536.     XOR    CL,CL        ;CL <- 0
  537.     CMP    CL,SIZFLG
  538.     JNZ    D5        ;If sort by size
  539.     CMP    CL,DTEFLG
  540.     JNZ    D4        ;If sort by date/time
  541.     CMP    CL,EXTFLG
  542.     JNZ    D3        ;If sort by ext
  543.     LEA    SI,[SI].NAM
  544.     LEA    DI,[DI].NAM
  545.     MOV    CX,1+SIZE NAM+SIZE EXT    ;# of bytes
  546.     JMP    SHORT D6
  547. D3:    LEA    SI,[SI].EXT    ;Sort by extension
  548.     LEA    DI,[DI].EXT
  549.     MOV    CX,SIZE EXT    ;# of bytes
  550.     JMP    SHORT D6
  551. D4:    LEA    SI,[SI].DTE    ;Sort by date/time
  552.     LEA    DI,[DI].DTE
  553.     MOV    CX,2        ;# of words
  554.     STD
  555.     REPZ    CMPSW
  556.     MOV    DI,DX
  557.     MOV    SI,AX
  558.     JBE    D2
  559.     JMP    SHORT D7
  560. D5:    LEA    SI,[SI].SZH    ;Sort by size
  561.     LEA    DI,[DI].SZH
  562.     MOV    CX,2        ;# of words
  563.     STD
  564.     REPZ    CMPSW
  565.     MOV    DI,DX
  566.     MOV    SI,AX
  567.     JBE    D2
  568.     JMP    SHORT D7
  569. D6:    CLD            ;Sort by name.ext
  570.     REPZ    CMPSB
  571.     MOV    DI,DX
  572.     MOV    SI,AX
  573.     JBE    D2
  574. D7:    MOV    [DI],SI
  575.     MOV    [BX],DI
  576.     ADD    DI,SIZE DIRNTRY ;Point to next entry
  577.     JMP    D1
  578. D8:    RET
  579. SRTDIRB ENDP
  580.  
  581.     SUBTTL
  582.     PAGE
  583. ; LNKDIRB - LINKS ENTRIES IN DIRBUF
  584.  
  585. LNKDIRB PROC    NEAR        ;LINK ENTRIES IN DIRBUF
  586.     MOV    DI,OFFSET DIRBUF
  587.     MOV    C1LNK,DI       ;Point to 1st entry
  588.     MOV    CX,NBRFILS    ;Set loop counter
  589.     DEC    CX
  590. LNK1:    MOV    BX,DI
  591.     ADD    DI,SIZE DIRNTRY ;Offset to next entry
  592.     MOV    [BX],DI     ;Store ptr
  593.     LOOP    LNK1        ;Link next entry
  594.     MOV    [DI],CX     ;Last ptr <- null
  595.     RET
  596. LNKDIRB ENDP
  597.  
  598. ; SPLTLST - SPLITS LINKED LIST IN HALF
  599.  
  600. SPLTLST PROC    NEAR
  601.     MOV    CX,NBRFILS    ;Get # of entries
  602.     SAR    CX,1        ; and divide by 2
  603.     JZ    F2        ;if NBRFILS < 2
  604.     ADC    CL,0        ;Account for odd #
  605.     MOV    BX,OFFSET C1LNK
  606. F1:    MOV    BX,[BX]     ;Chain thru list to
  607.     LOOP    F1        ; last row of column 1.
  608.     MOV    AX,[BX]     ;Get ptr to 1st row of col 2
  609.     MOV    C2LNK,AX    ; C2LNK <- R1,C2 ptr
  610.     MOV    [BX],CX     ;Last row of col 1 <- null
  611. F2:    RET
  612. SPLTLST ENDP
  613.  
  614.     SUBTTL    GETFREE - GET DISK FREE SPACE
  615.     PAGE
  616. GETFREE PROC        NEAR        ;cluster = allocation unit
  617.     MOV     DL,DRVNBR        ;Get drive #
  618.     PUSH    DS            ;Save DS
  619.     DOSCALL @GETVER        ;get DOS version number               JYF
  620.     CMP     AL,2        ;is this version 2.0 or higher?           JYF
  621.     JGE     E4            ;yes                       JYF
  622.                 ;no                        JYF
  623.     DOSCALL @FATAD2        ;Get FAT info from DOS
  624.     MOV     AH,0        ;AL = sector size
  625.     XCHG    CX,DX        ;Sector size times the
  626.     MUL     DX            ; # sectors/cluster
  627.     PUSH    AX            ;Save cluster size
  628.     XOR     AX,AX        ;Unused clusters = 0
  629.     MOV     SI,2        ;Skip first 3 clusters
  630. E1: MOV     DI,SI        ;DI <- cluster #
  631.     SHR     DI,1        ;Divide cluster number
  632.     ADD     DI,SI        ; by 1.5
  633.     MOV     DI,[BX+DI]        ;Fetch from FAT
  634.     TEST    SI,1        ;Test if even or odd
  635.     JZ        E2            ;If even then skip
  636.     SHR     DI,1        ; else if odd
  637.     SHR     DI,1        ;  right justify the
  638.     SHR     DI,1        ;  cluster number.
  639.     SHR     DI,1
  640. E2: AND     DI,0FFFH        ;Mask the low 12 bits
  641.     JNZ     E3            ;If not 0 then skip, else
  642.     INC     AX            ; increment counter.
  643. E3: INC     SI            ;Point to next cluster
  644.     LOOP    E1            ; and go check it.
  645.     POP     CX            ;Get cluster size, times
  646.     MUL     CX            ;  # of free clusters
  647.     JMP     E5            ;skip processing for DOS 2.0        JYF
  648. E4:                ;processing for DOS 2.00            JYF
  649.     DOSCALL @DSKFSP        ;get disk free space            JYF
  650.     MUL     BX            ;AX (sectors/clustor) * BX (free clustors)    JYF
  651.     MOV     DX,AX        ;                        JYF
  652.     MUL     CX            ;AX * CX (bytes/clustor)            JYF
  653. E5:                ;                        JYF
  654.     POP     DS            ;Restore DS
  655.     MOV     LOSIZE,AX        ;Save the 32 bit
  656.     MOV     HISIZE,DX        ; binary free space
  657.     RET
  658. GETFREE ENDP
  659.  
  660.     SUBTTL  PRTHDNG - PRINT HEADINGS
  661.     PAGE
  662. PRTHDNG PROC        NEAR
  663.     MOV    AL,CLSFLG
  664.     OR    AL,AL
  665.     JNZ    G1        ;If not erase screen
  666.     SUB    CX,CX
  667.     MOV    DX,24*256+79    ;row=24 col=79
  668.     MOV    BH,7        ;Video mode
  669.     MOV    AX,0600H
  670.     INT    10H        ;BIOS video call
  671.     SUB    DX,DX
  672.     MOV    AH,2        ;Clear screen
  673.     MOV    BH,0
  674.     INT    10H        ;BIOS video call
  675. G1:    MOV    AL,DRVNBR    ;Get drive #
  676.     DOSCALL @GETDTE ; CX<-year, DH<-month, DL<-day
  677.     MOV    AL,DH
  678.     AAM
  679.     XCHG    AL,AH
  680.     OR    D_MM,AX     ;Fold into month
  681.     MOV    AL,DL
  682.     AAM
  683.     XCHG    AL,AH
  684.     OR    D_DD,AX     ;Fold into day
  685.     MOV    AX,CX
  686.     SUB    AX,1900
  687.     AAM
  688.     XCHG    AL,AH
  689.     OR    D_YY,AX     ;Fold into year
  690.     DOSCALL @GETTME ; CH<-hours, CL<-minutes
  691.     MOV    AL,CH        ;AL<-binary hours
  692.     AAM            ;Convert AL to two
  693.     XCHG    AL,AH        ; BCD digits in AX.
  694.     OR    T_HH,AX     ;Fold into hours
  695.     MOV    AL,CL        ;AL<-binary minutes
  696.     AAM            ;Convert AL to two
  697.     XCHG    AL,AH        ; BCD digits in AX.
  698.     OR    T_MM,AX     ;Fold into minutes
  699.     DOSCALL @STROUT,HDNG1    ;Print main heading
  700.     MOV    DX,OFFSET HDNG2 ;point to 2nd heading            2.3
  701.     ADD    DX,HOLDLEN    ;add offset length to center DIRNAME    2.3
  702.     DOSCALL @STROUT     ;Print subheading            2.3
  703.     DOSCALL @STROUT,HDNG3    ;Print column 1 heading
  704.     CMP    WORD PTR C2LNK,0
  705.     JZ    G2        ;If not 2 columns
  706.     DOSCALL @STROUT,SPACES-3 ;Print 3 spaces            2.4
  707.     DOSCALL @STROUT,HDNG3    ;Print column 2 heading
  708. G2:    DOSCALL @STROUT,CRLF    ;Start a new line
  709.     RET
  710. PRTHDNG ENDP
  711.  
  712.     SUBTTL    PRINT DETAIL LINES
  713.     PAGE
  714. PRTDRVR PROC    NEAR        ;Driver routine
  715.     MOV    BX,C1LNK
  716.     OR    BX,BX        ;more to print?
  717.     JZ    H2        ; no, return
  718.     MOV    AX,[BX]
  719.     MOV    C1LNK,AX
  720.     CALL    PRTDTL        ;print column one
  721.     MOV    BX,C2LNK
  722.     OR    BX,BX
  723.     JZ    H1        ;If no column 2 entry
  724.     DOSCALL @STROUT,SPACES-3 ;print 3 spaces            2.4
  725.     MOV    AX,[BX]
  726.     MOV    C2LNK,AX
  727.     CALL    PRTDTL        ;print column two
  728. H1:    DOSCALL @STROUT,CRLF
  729.     CMP    PSEFLG,0    ;Check for pause option
  730.     JZ    PRTDRVR     ;Nope, continue
  731.     DEC    LINCNT        ;Decrement line counter
  732.     JNZ    PRTDRVR     ;If page not full?
  733.     MOV    LINCNT,LPERSCR-2 ;Reset to # lines/screen
  734.     DOSCALL @STROUT,PSEMSG    ;Display pause message.
  735.     MOV    AL,@KEYIN    ;Specify input function
  736.     DOSCALL @CKEYIN     ;Wait for key press
  737.     DOSCALL @STROUT,CRLF    ;Set to new line
  738.     JMP    PRTDRVR     ;Go do the next line
  739. H2:    RET
  740. PRTDRVR ENDP
  741.  
  742. PRTDTL    PROC    NEAR        ;Prints file.ext, size, date & time
  743.     MOV    CX,1+SIZE NAM+SIZE EXT    ;                2.4
  744.     SUB    DI,DI        ;DI <- 0
  745. I1:    DOSCALL @CHROUT,[BX+DI].NAM
  746.     INC    DI        ;point to next char.
  747.     LOOP    I1        ;go do next char.
  748.     TEST    BYTE PTR [BX].ATR,10H ;is it a directory entry?     2.4
  749.     JZ    I2        ;no, print size             2.4
  750.     DOSCALL @STROUT,PRTDIR    ;yes, print <DIR> instead of size    2.4
  751.     JMP    I3        ;and bypass size print            2.4
  752. I2:    PUSH    BX        ;save entry base
  753.     MOV    SI,[BX].SZL    ;SI <- low size
  754.     MOV    DI,[BX].SZH    ;DI <- high size
  755.     ADD    LOTOTAL,SI    ;add low-order word to total        2.3
  756.     ADC    HITOTAL,DI    ;and add high-order word to total    2.3
  757.     CALL    PRINTDX     ;convert size                2.4
  758.     MOV    DX,OFFSET DOUBLE+1 ;point past first byte of decimal #    2.4
  759.     DOSCALL @STROUT     ;Print size                2.4
  760.     POP    BX        ;restore entry base
  761. I3:    MOV    CX,5        ;we need to move 5 bytes        2.4
  762.     MOV    SI,OFFSET INITATR ;to initialize PRTATR         2.4
  763.     MOV    DI,OFFSET PRTATR  ;with spaces                2.4
  764.     CLD            ;just in case                2.4
  765.     REP    MOVSB        ;now move the spaces            2.4
  766.     TEST    BYTE PTR [BX].ATR,10H ;is it a directory file?        2.4
  767.     JNZ    I24X        ;yes, bypass the other tests        2.4
  768.     MOV    DI,OFFSET PRTATR+3 ;point to right side of field    2.4
  769.     STD            ;and work backwards            2.4
  770.     TEST    BYTE PTR [BX].ATR,20H ;is it an archived file?        2.4
  771. ;note that the archive bit is set OFF when the file is archived...    2.4
  772.     JNZ    I24H        ;no, test for hidden file        2.4
  773.     MOV    AL,'A'          ;get flag character                     2.4
  774.     STOSB            ;and put it into PRTATR         2.4
  775. I24H:    TEST    BYTE PTR [BX].ATR,02H ;is it a hidden file?        2.4
  776.     JZ    I24R        ;no, test for r/o file            2.4
  777.     MOV    AL,'H'          ;get flag character                     2.4
  778.     STOSB            ;and put it into PRTATR         2.4
  779. I24R:    TEST    BYTE PTR [BX].ATR,01H ;is it a r/o file?        2.4
  780.     JZ    I24S        ;no, test for system file        2.4
  781.     MOV    AL,'R'          ;get flag character                     2.4
  782.     STOSB            ;and put it into PRTATR         2.4
  783. I24S:    TEST    BYTE PTR [BX].ATR,04H ;is it a system file?        2.4
  784.     JZ    I24X        ;no, exit tests             2.4
  785.     MOV    AL,'S'          ;get flag character                     2.4
  786.     STOSB            ;and put it into PRTATR         2.4
  787. I24X:    DOSCALL @STROUT,PRTATR    ;Print the attribute characters     2.4
  788.     MOV    AX,[BX].DTE    ;AX <- packed date
  789.     CALL    PRTDTE
  790.     DOSCALL @STROUT,SPACES-1 ;print 1 space             2.4
  791.     MOV    AX,[BX].TME    ;AX <- packed time
  792.     CALL    PRTTME
  793.     RET
  794. PRTDTL    ENDP
  795.  
  796.     SUBTTL    PRINTDD - PRINT A DOUBLE WORD IN DI:SI
  797.     PAGE
  798. PRINTDD PROC    NEAR        ;Prints a 32 bit integer in DI:SI
  799.     CALL    PRINTDX     ;format the double word into DOUBLE    2.4
  800.     DOSCALL @STROUT,DOUBLE    ;print the digits            2.4
  801.     RET            ;and return                2.4
  802. PRINTDD ENDP            ;                    2.4
  803.  
  804. PRINTDX PROC    NEAR        ;converts integer in DI:SI to decimal    2.4
  805.     MOV    DBLCNT,0    ;reset the offset for DOUBLE        2.4
  806.     XOR    AX,AX        ;Zero out the                2.4
  807.     MOV    BX,AX        ; working
  808.     MOV    BP,AX        ; registers.
  809.     MOV    CX,32        ;# bits of precision
  810. J1:    SHL    SI,1
  811.     RCL    DI,1
  812.     XCHG    BP,AX
  813.     CALL    J6
  814.     XCHG    BP,AX
  815.     XCHG    BX,AX
  816.     CALL    J6
  817.     XCHG    BX,AX
  818.     ADC    AL,0
  819.     LOOP    J1
  820.     MOV    CX,1710H    ;5904 ?
  821.     MOV    AX,BX
  822.     CALL    J2
  823.     MOV    AX,BP
  824. J2:    PUSH    AX
  825.     MOV    DL,AH
  826.     CALL    J3
  827.     POP    DX
  828. J3:    MOV    DH,DL
  829.     SHR    DL,1        ;Move high
  830.     SHR    DL,1        ; nibble to
  831.     SHR    DL,1        ; the low
  832.     SHR    DL,1        ; position.
  833.     CALL    J4
  834.     MOV    DL,DH
  835. J4:    AND    DL,0FH        ;Mask low nibble
  836.     JZ    J5        ;If not zero
  837.     MOV    CL,0
  838. J5:    DEC    CH
  839.     AND    CL,CH
  840.     OR    DL,'0'          ;Fold in ASCII zero
  841.     SUB    DL,CL
  842.     PUSH    DI        ;save DI                2.4
  843.     MOV    DI,OFFSET DOUBLE ;point to DOUBLE            2.4
  844.     ADD    DI,DBLCNT    ;add current offset            2.4
  845.     INC    DBLCNT        ;bump offset for next time        2.4
  846.     MOV    BYTE PTR [DI],DL ;move next digit to DOUBLE        2.4
  847.     POP    DI        ;restore DI                2.4
  848.     RET            ;Exit to caller
  849. PRINTDX ENDP            ;                    2.4
  850.  
  851. J6    PROC    NEAR
  852.     ADC    AL,AL
  853.     DAA
  854.     XCHG    AL,AH
  855.     ADC    AL,AL
  856.     DAA
  857.     XCHG    AL,AH
  858.     RET
  859. J6    ENDP
  860.  
  861.     SUBTTL    PRINT DATE, TIME & # FILES ROUTINES
  862.     PAGE
  863. PRTDTE    PROC    NEAR    ;Print packed date in AX as MM/DD/YY
  864.     OR    AX,AX
  865.     JNZ    K1        ;If date <> 0
  866.     DOSCALL @STROUT,SPACES-8 ;Print 8 spaces
  867.     RET
  868. K1:    PUSH    AX
  869.     AND    AX,MASK P_MO    ;Mask the month,
  870.     MOV    CL,P_MO     ; set shift count,
  871.     SHR    AX,CL        ; right justify, &
  872.     CALL    PRTBCD        ; print it.
  873.     DOSCALL @CHROUT,'/'
  874.     POP    AX
  875.     PUSH    AX
  876.     AND    AX,MASK P_DY    ;Mask the day &
  877.     CALL    PRTBCD        ; print it.
  878.     DOSCALL @CHROUT,'/'
  879.     POP    AX
  880.     AND    AX,MASK P_YR    ;Mask the year,
  881.     MOV    CL,P_YR     ; set shift count,
  882.     SHR    AX,CL        ; right justify,
  883.     ADD    AX,80        ; add in year bias, &
  884.                 ; print it.
  885. PRTBCD: AAM            ;Convert AL to BCD
  886.     OR    AX,'00'         ;Convert to ASCII
  887.     PUSH    AX
  888.     DOSCALL @CHROUT,AH    ;High order digit
  889.     POP    AX
  890.     DOSCALL @CHROUT,AL    ;Low order digit
  891.     RET
  892. PRTDTE    ENDP
  893.  
  894. PRTTME    PROC    NEAR    ;Print packed time in AX as HH:MM
  895.     OR    AX,AX
  896.     JNZ    L1
  897.     DOSCALL @STROUT,SPACES-5 ;Print 5 spaces
  898.     RET
  899. L1:    PUSH    AX
  900.     AND    AX,MASK P_HR    ;Mask the hours,
  901.     MOV    CL,P_HR     ; set shift count,
  902.     SHR    AX,CL        ; right justify, &
  903.     CALL    PRTBCD        ; print it.
  904.     DOSCALL @CHROUT,':'
  905.     POP    AX
  906.     AND    AX,MASK P_MI    ;Mask the minutes,
  907.     MOV    CL,P_MI     ; set shift count,
  908.     SHR    AX,CL        ; right justify, &
  909.     CALL    PRTBCD        ; print it.
  910.     RET
  911. PRTTME    ENDP
  912.  
  913. PRTNFLS PROC    NEAR        ;print byte total and number of files    2.3
  914.     MOV    SI,LOTOTAL    ;get low-order word of total        2.3
  915.     MOV    DI,HITOTAL    ;get high-order word of total        2.3
  916.     CALL    PRINTDD     ;and print the total            2.3
  917.     DOSCALL @STROUT,HDNG4    ;follow the total with a message    2.3
  918.     MOV    SI,NBRFILS    ;get # of files
  919.     XOR    DI,DI        ;zero high order
  920.     CALL    PRINTDD     ;Print # of files
  921.     DOSCALL @STROUT,HDNG5    ;follow it with a heading
  922.     MOV    SI,LOSIZE    ;get low-order word of freespace    2.4
  923.     MOV    DI,HISIZE    ;get high-order word of freespace    2.4
  924.     CALL    PRINTDD     ;and print freespace            2.4
  925.     DOSCALL @STROUT,HDNG6    ;follow the freespace with explanation    2.4
  926.     RET
  927. PRTNFLS ENDP
  928.     EVEN
  929. DIRBUF    DIRNTRY <>    ;Buffer for directory entries
  930. SDIR    ENDS
  931.     END    MAIN
  932.